package com.zxx.libinject.apt;

import com.zxx.libinject.anno.AnnotationHandler;
import com.zxx.libinject.anno.ViewInjectHandler;
import com.zxx.libinject.apt.AdapterWriter;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;

import static javax.tools.Diagnostic.Kind.ERROR;

/**
 * @author zxx on 2021/4/22
 */
@SupportedAnnotationTypes("com.zxx.libinject.anno.*")   //中填写待处理的注解全称
@SupportedSourceVersion(SourceVersion.RELEASE_6)        //表示处理的JAVA版本。
public class ViewInjectorProcessor extends AbstractProcessor {

    /**
     * 所有注解处理器的列表
     */
    List<AnnotationHandler> mHandlers = new LinkedList<>();

    /**
     * 类型与字段的关联表,用于在写入Java文件时按类型来写不同的文件和字段
     */
    Map<String, List<VariableElement>> map = new HashMap<>();

    AdapterWriter mWriter;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        registerHandler();
        mWriter = new DefaultJavaFileWriter(processingEnv);
    }

    private void registerHandler() {
        mHandlers.add(new ViewInjectHandler());
    }

    //编译时候将会执行process方法
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (AnnotationHandler handler : mHandlers) {
            // 关联ProcessingEnvironment
            handler.attachProcessingEnv(processingEnv);

            // 解析注解相关的信息
            map.putAll(handler.handleAnnotation(roundEnv));
        }

        // 将解析到的数据写入到具体的类型中
        mWriter.generate(map);
        return true;
    }

    protected void error(Element element, String message, Object... args) {
        if (args.length > 0) {
            message = String.format(message, args);
        }
        processingEnv.getMessager().printMessage(ERROR, message, element);
    }

}
